using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Interop.Word;
using RecruitmentAgency.Models.DataTypes;
using System.Drawing;
using System.Net;
using System.IO;

namespace RecruitmentAgency.Models.Utilities
{
    /// <summary>
    /// The RecruitmentAgency.Models.Utilities.WordDocumentCreator is a helper class that uses the Microsoft.Office.Interop.Word classes to create and opens a CV in Microsoft Word format from a CvData instance
    /// </summary>
    public class WordDocumentCreator
    {
        private int endPosition = 0;
        private object filePath, missing = System.Reflection.Missing.Value, visible = true, start = 0, end = 0;
        private ApplicationClass wordApplication;
        private Document document;
        private object lineBreak = WdBreakType.wdLineBreak;
        private object collapseEnd = WdCollapseDirection.wdCollapseEnd;

        /// <summary>
        /// Initialises a new RecruitmentAgency.Models.Utilities.WordDocumentCreator instance
        /// </summary>
        public WordDocumentCreator(string filePath)
        {
            this.filePath = filePath;
            wordApplication = new ApplicationClass();
            document = wordApplication.Documents.Add(ref missing, ref missing, ref missing, ref missing);
        }

        /// <summary>
        /// Creates and opens a CV in Microsoft Word format from a CvData instance
        /// </summary>
        /// <param name="cvData">The CV data to create the Word document with</param>
        public void CreateWordDocumentFromCvData(CvData cvData)
        {
            PersonalDetail personalDetail = cvData.PersonalDetail;
            string middleNames = string.IsNullOrEmpty(personalDetail.MiddleNames) ? string.Empty : " " + personalDetail.MiddleNames;
            string fullName = string.Format("{0}{1} {2}", personalDetail.FirstName, middleNames, personalDetail.LastName);
            StringBuilder address = new StringBuilder(personalDetail.AddressLine1 + ", ");
            if (!string.IsNullOrEmpty(personalDetail.AddressLine2)) address.Append(personalDetail.AddressLine2 + ", ");
            address.Append(personalDetail.Town + ", ");
            address.Append(personalDetail.PostCode);
            StringBuilder contacts = new StringBuilder();
            if (!string.IsNullOrEmpty(personalDetail.HomePhone)) contacts.Append(personalDetail.HomePhone);
            if (!string.IsNullOrEmpty(personalDetail.MobilePhone))
            {
                if (contacts.Length > 0) contacts.Append(" / ");
                contacts.Append(personalDetail.MobilePhone);
            }
            if (!string.IsNullOrEmpty(personalDetail.Email1))
            {
                if (contacts.Length > 0) contacts.Append(" / ");
                contacts.Append(personalDetail.Email1);
            }
            if (!string.IsNullOrEmpty(personalDetail.Email2))
            {
                if (contacts.Length > 0) contacts.Append(" / ");
                contacts.Append(personalDetail.Email2);
            }
            SetLeftIndent(0);
            // add user photo if one exists
            if (!string.IsNullOrEmpty(personalDetail.PhotoUrl))
            {
                wordApplication.Selection.InlineShapes.AddPicture(personalDetail.PhotoUrl, ref missing, ref missing, ref missing);
                wordApplication.Selection.TypeParagraph();
                wordApplication.Selection.TypeParagraph();
            }
            // build header
            SetFont("Segoe UI", 20.0f, true, false, false, WdColor.wdColorBlack);
            AddParagraph(fullName);
            SetFont("Segoe UI", 13.0f, true, false, false, WdColor.wdColorBlack);
            AddParagraph(address.ToString());
            AddParagraph(contacts.ToString());
            if (!string.IsNullOrEmpty(personalDetail.WebsiteUrl)) AddParagraph("www." + personalDetail.WebsiteUrl);
            if (!string.IsNullOrEmpty(personalDetail.DateOfBirth)) AddParagraph(DateTime.Parse(personalDetail.DateOfBirth).ToLongDateString());
            wordApplication.Selection.TypeParagraph();
            wordApplication.Selection.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphLeft;
            AddLineShape(10);
            wordApplication.Selection.TypeParagraph();
            // add CV details
            if (cvData.PersonQualifications.Count > 0)
            {
                SetFont("Segoe UI", 14.0f, true, false, false, WdColor.wdColorBlack);
                AddParagraph("Qualifications");
                SetFont("Segoe UI", 12.0f, false, false, false, WdColor.wdColorBlack);
                foreach (PersonQualification qualification in cvData.PersonQualifications)
                {
                    if (qualification.QualificationVerified)
                    {
                        AddParagraph("\u2022 " + qualification.ToShortString());
                    }
                }
                wordApplication.Selection.TypeParagraph();
            }
            AddLineShape(10);
            wordApplication.Selection.InsertBreak(ref lineBreak);
            if (cvData.PersonEmployments.Count > 0)
            {
                SetFont("Segoe UI", 14.0f, true, false, false, WdColor.wdColorBlack);
                AddParagraph("Employment record");
                foreach (PersonEmployment employment in cvData.PersonEmployments)
                {
                    if (employment.EmploymentVerified)
                    {
                        string employmentString = string.Format(string.Format("Worked as a {0} at {1} from {2} to {3} in the {4} sector.", employment.JobTitle, employment.CompanyName, (DateTime.Parse(employment.StartDate)).ToLongDateString(), (DateTime.Parse(employment.EndDate)).ToLongDateString(), employment.IndustrySector));
                        SetFont("Segoe UI", 12.0f, false, false, false, WdColor.wdColorBlack);
                        AddParagraph(employment.ToLongString());
                        SetFont("Segoe UI", 12.0f, false, true, false, WdColor.wdColorBlack);
                        AddParagraph("\u2022 " + employment.KeyDuties);
                        wordApplication.Selection.TypeParagraph();
                    }
                }
            }
            AddLineShape(10);
            wordApplication.Selection.InsertBreak(ref lineBreak);
            if (cvData.PersonSkills.Count > 0)
            {
                SetFont("Segoe UI", 14.0f, true, false, false, WdColor.wdColorBlack);
                AddParagraph("Current skills");
                SetFont("Segoe UI", 12.0f, false, false, false, WdColor.wdColorBlack);
                foreach (PersonSkill skill in cvData.PersonSkills)
                {
                    if (skill.SkillVerified)
                    {
                        AddParagraph("\u2022 " + skill.ToShortString());
                    }
                }
                wordApplication.Selection.TypeParagraph();
            }
            AddLineShape(10);
            wordApplication.Selection.InsertBreak(ref lineBreak);
            if (cvData.PersonReferees.Count > 0)
            {
                SetFont("Segoe UI", 14.0f, true, false, false, WdColor.wdColorBlack);
                AddParagraph("Referees");
                SetFont("Segoe UI", 12.0f, false, false, false, WdColor.wdColorBlack);
                foreach (PersonReferee referee in cvData.PersonReferees)
                {
                    if (referee.RefereeVerified)
                    {
                        address = new StringBuilder(referee.RefereeAddressLine1 + ",\n");
                        if (!string.IsNullOrEmpty(referee.RefereeAddressLine2)) address.Append(referee.RefereeAddressLine2 + ",\n");
                        address.Append(referee.RefereeTown + ",\n");
                        address.Append(referee.RefereePostCode);
                        AddParagraph(referee.RefereeFirstName + " " + referee.RefereeLastName);
                        AddParagraph(address.ToString());
                        AddParagraph(referee.RefereePhone);
                        AddParagraph(referee.Email);
                        wordApplication.Selection.TypeParagraph();
                    }
                }
            }
            Save();
            wordApplication.Visible = true;
        }

        private void AddParagraph(string text)
        {
            wordApplication.Selection.TypeText(text);
            wordApplication.Selection.TypeParagraph();
            endPosition += text.Length + 1;
        }

        private void AddLineShape(int distanceAboveText)
        {
            start = wordApplication.Selection.Range.End - 1;
            object range = document.Range(ref start, ref missing);
            ((Range)range).InlineShapes.AddHorizontalLineStandard(ref missing);
        }

        private void SetFont(string name, float size, bool bold, bool italic, bool underline, WdColor colour)
        {
            wordApplication.Selection.Font.Color = colour;
            wordApplication.Selection.Font.Name = name;
            wordApplication.Selection.Font.Size = size;
            wordApplication.Selection.Font.Bold = bold ? 1 : 0;
            wordApplication.Selection.Font.Italic = italic ? 1 : 0;
            wordApplication.Selection.Font.Underline = underline ? WdUnderline.wdUnderlineThick : WdUnderline.wdUnderlineNone;
        }

        private void SetLeftIndent(int leftIndent)
        {
            Paragraph paragraph = wordApplication.Selection.Paragraphs.Add(ref missing);
            paragraph.LeftIndent = (float)leftIndent;
        }

        private void Save()
        {
            document.SaveAs(ref filePath, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
        }
    }
}